iT邦幫忙

2026 iThome 鐵人賽

DAY 8
0
AI Engineering

Harness Engineering × Pi Agent 實戰:打造可觀測、可評估的 AI Coding Agent系列 第 8 篇

Day8:Agent 如何讀懂專案規則?拆解 AGENTS.md 的載入與優先順序

  • 分享至 

  • xImage
  •  

今天拆第一個元件

量測台搭好了,第一輪「拆一個元件、隔天量它」從 AGENTS.md 開始。它是 Day3 地圖上「看現況」那一站最重要的東西:把「這個專案該怎麼做事」寫成一份說明書,讓模型在動手之前就知道。

用過 coding agent 的人大多寫過這種檔案。但你知道 Pi 會從哪些地方找它嗎?專案裡同時有 AGENTS.md 和 CLAUDE.md 時聽誰的?子目錄的規則會不會蓋掉上層的?這些問題文件只寫了幾行,今天直接看原始碼。

會去哪些地方找

Pi 啟動時會找這幾個地方:

  1. Pi 家目錄底下的 AGENTS.md(全域規則,預設是 ~/.pi/agent/AGENTS.md)
  2. 從目前工作目錄開始,一路往上到檔案系統根目錄的每一層
  3. 目前工作目錄本身

注意第 2 點是一路往上走到根目錄,不是停在 git repo 的根。如果你在 D:\work\ 放了一份 AGENTS.md,底下所有專案都會吃到它。

同一個目錄:只取一個

每個目錄 Pi 只會拿一個檔案,照這個順序找,找到就停:

// dist/core/resource-loader.js
function loadContextFileFromDir(dir) {
    const candidates = ["AGENTS.override.md", "AGENTS.md", "AGENTS.MD", "CLAUDE.md", "CLAUDE.MD"];
    for (const filename of candidates) {
        // 第一個存在的檔案就回傳
    }
}

所以:

  • 同一個目錄同時有 AGENTS.md 和 CLAUDE.md,只有 AGENTS.md 會被載入,CLAUDE.md 被完全忽略。
  • AGENTS.override.md 存在時,同目錄的 AGENTS.md、CLAUDE.md 都不會被載入。它適合放「只在我這台電腦生效、不想 commit 進 repo」的規則。

不同目錄之間:不覆蓋,而是疊加

這是最容易誤會的地方。子目錄的 AGENTS.md 不會蓋掉上層的,所有找到的檔案都會一起送進去:

// dist/core/resource-loader.js(節錄)
const contextFiles = [];
if (globalContext) contextFiles.push(globalContext);   // 全域的放第一個

const ancestorContextFiles = [];
let currentDir = cwd;
while (true) {
    const contextFile = loadContextFileFromDir(currentDir);
    if (contextFile) ancestorContextFiles.unshift(contextFile);  // 越上層越往前插
    const parentDir = dirname(currentDir);
    if (parentDir === currentDir) break;
    currentDir = parentDir;
}
contextFiles.push(...ancestorContextFiles);

往上走的時候用 unshift 往陣列前面插,結果是:全域的最前面,接著從根目錄往下,離工作目錄最近的放最後面。

Pi 怎麼挑 context 檔、放到哪裡

那兩份規則互相矛盾時聽誰的?Pi 沒有做任何合併或裁決,全部原封不動交給模型自己判斷。實務上模型通常比較重視後面出現的內容,但這不是保證。與其賭模型的判斷,比較好的做法是讓子目錄的規則只補充、不要跟上層打架。

它最後放在 system prompt 的哪裡

載入的檔案會被包進一段 XML 標籤,接在 Pi 的預設 system prompt 後面:

// dist/core/system-prompt.js(節錄)
prompt += "\n\n<project_context>\n\n";
prompt += "Project-specific instructions and guidelines:\n\n";
for (const { path: filePath, content } of contextFiles) {
    prompt += `<project_instructions path="${filePath}">\n${content}\n</project_instructions>\n\n`;
}
prompt += "</project_context>\n";

整個 system prompt 的順序是:

  1. Pi 預設 prompt(工具清單、Guidelines)
  2. --append-system-prompt 指定的內容
  3. <project_context>:所有 context 檔
  4. <available_skills>:可用 skills 的名稱與描述
  5. Current working directory: ...

幾個由此延伸出來的事實:

  • 就算用 .pi/SYSTEM.md 把預設 prompt 整個換掉,context 檔還是會被接在後面。要真正關掉,得用 --no-context-files。
  • 每個檔案都會帶著自己的路徑,模型看得到規則是從哪一層來的。
  • Day6 提過 session 記錄不會存 system prompt,所以你在記錄裡永遠看不到 AGENTS.md 被 read——它是在迴圈開始前就被塞進去的。

一個安全上要知道的細節

Pi 有「專案信任」機制:沒被信任的專案,.pi/ 底下的 extension、skill、設定都不會載入。但官方文件寫得很清楚——context 檔不受信任機制限制,一律會載入。

換句話說,你 clone 一個陌生的 repo 下來、在裡面啟動 Pi,那個 repo 的 AGENTS.md 就已經在 system prompt 裡了。它能要求模型做任何事。處理不信任的程式碼時,記得加上 --no-context-files,或是在隔離環境裡跑。

這對實驗設計的影響

理解載入規則之後,量測台有兩個設計就說得通了:

  1. 每次執行都在獨立目錄進行,而且上層目錄是乾淨的。 因為 Pi 會一路往上找到根目錄,只要任何一層祖先目錄有 AGENTS.md,「無 AGENTS.md」這個條件就被汙染了。開跑前我檢查過 D:\ 和 Pi 家目錄底下都沒有這些檔案。
  2. 「無 AGENTS.md」是把檔案刪掉,而不是加 --no-context-files。 兩者對 Pi 的效果一樣,但刪檔案是每一種 harness 都適用的操作,換成別的 coding agent 也能跑出可比較的結果;旗標則是 Pi 專屬的。

明天

Day9 會量這個元件到底值多少:同樣的任務,有 AGENTS.md 和沒有 AGENTS.md,成功率、成本、工具呼叫次數各差多少。先偷偷透露一點校準時看到的現象——成功率的差距比預期小,但另一個數字差很多。


上一篇
Day7:如何公平評估 Coding Agent?打造可重複、可驗證的量測台
下一篇
Day9:AGENTS.md 真正改善了什麼?30 次對照實驗的意外答案
系列文
Harness Engineering × Pi Agent 實戰:打造可觀測、可評估的 AI Coding Agent 共 11 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言